// ------------------------------------------------------------------------
// 项目名称：Canroc.Net 
// 版权归属：Canroc（https://gitee.com/canroc）
//
// 许可证信息
// Canroc.Net项目主要遵循 Apache 许可证（版本 2.0）进行分发和使用。许可证位于源代码树根目录中的 LICENSE-APACHE 文件。
//
// 使用条款：
// 1.使用本项目应遵守相关法律法规和许可证的要求。
// 2.不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动。
// 3.任何基于本项目二次开发而产生的一切法律纠纷和责任，我们不承担任何责任
//
// 免责声明
// 对于因使用本代码而产生的任何直接、间接、偶然、特殊或后果性损害，我们不承担任何责任。
//
// 其他重要信息
// Canroc.Net 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。
// ------------------------------------------------------------------------

using System.Net.Http.Headers;

namespace Canroc.Net.RemoteHttp.WeChatPay.Handler;

/// <summary>
///     微信支付请求处理
/// </summary>
public class WeChatPayDelegatingHandler : DelegatingHandler
{
    /// <summary>
    ///     请求拦截处理
    /// </summary>
    /// <param name="request"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
        CancellationToken cancellationToken)
    {
        var options = App.GetOptions<WeChatPayOptions>();
        if (options.RSAPrivateKey is null)
        {
            throw Oops.Oh("微信支付证书未找到，无法签名此请求！");
        }

        var nonceStr = Guid.NewGuid().ToString("N");
        var timestamp = DateTimeOffset.Now.ToUnixTimeSeconds();

        #region 计算请求签名

        var sign = new StringBuilder();
        sign.Append($"{request.Method.Method.ToUpper()}\n");
        sign.Append($"/{request.RequestUri}\n");
        sign.Append($"{timestamp}\n");
        sign.Append($"{nonceStr}\n");
        var content = request.Method != HttpMethod.Get
            ? await request.Content?.ReadAsStringAsync(cancellationToken)!
            : "";
        sign.Append($"{content}\n");

        // 使用 SHA256 with RSA 计算签名
        var signBytes = Encoding.UTF8.GetBytes(sign.ToString());
        var encryptionBytes =
            options.RSAPrivateKey.SignData(signBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
        var signature = Convert.ToBase64String(encryptionBytes);

        #endregion

        // 添加鉴权信息
        request.Headers.Authorization = new AuthenticationHeaderValue(
            "WECHATPAY2-SHA256-RSA2048",
            $"mchid=\"{options.MchId}\",serial_no=\"{options.CertificateSerialNo}\",nonce_str=\"{nonceStr}\",timestamp=\"{timestamp}\",signature=\"{signature}\"");

        // 发送请求并获取响应
        return await base.SendAsync(request, cancellationToken);
    }
}